# 【库说明】
"""
# 数理统计系列库

## 简介

+ 库名：stats_origin.py
+ 功能：统计量函数

## 库函数

+ sum(X)
+ ave(X)
+ var(X)
+ std(X)
+ cov(X)
+ cor(X)

## 更多信息

+ 作者：Kiana Kaslana
+ 个人邮箱：smilewwc@qq.com
+ 开源地址：https://gitee.com/Acrylic-Studio/Mathematical-Statistics

## 更新日志

+ 更新：2021.8.14
+ 创建日期：2020.9.20

## 开发者

+ Gitee: https://gitee.com/Acrylic-Studio
+ Email: smilewwc@qq.com
---------
Copyright © 2019~2021 Wang Weichen. All Rights Reserved.
"""

# 特殊属性
__author__ = "Wang Weichen"
__all__ = [""]


# 【导入库】
# 第三方库
import math
# 自定义库
from basefunction import *


# 【统计量函数定义】
def sum(X: list) -> float:
    """
    【函数】

    功能：计算样本的总和（Sum）

    参数：
    + X：[list 列表] 包含样本数据的Python列表

    返回值：
    + [float 浮点型] 列表中所有元素的总和
    """
    X_sum = 0
    for x_i in X:
        X_sum = X_sum + x_i
    return X_sum


def ave(X: list) -> float:
    """
    【函数】

    功能：计算样本的均值（Average）

    参数：
    + X：[list 列表] 包含样本数据的Python列表

    返回值：
    + [float 浮点型] 列表中所有元素的均值
    """
    n = len(X)
    X_ave = sum(X) / n
    return X_ave


def var(X: list, ddof: int = 1) -> float:
    """
    【函数】

    功能：计算样本的方差（Variance），默认计算修正值

    参数：
    + X：[list 列表] 包含样本数据的Python列表

    返回值：
    + [float 浮点型] 列表中所有元素的方差
    """
    n = len(X)
    S = 0
    X_ave = ave(X)
    for x_i in X:
        S = S + (x_i - X_ave)**2
    X_var = S / (n-ddof)
    return X_var


def std(X: list, ddof: int = 1) -> float:
    """
    【函数】

    功能：计算样本的标准差（Standard deviation），默认计算修正值

    参数：
    + X：[list 列表] 包含样本数据的Python列表

    返回值：
    + [float 浮点型] 列表中所有元素的标准差
    """
    n = len(X)
    X_std = math.sqrt(var(X, ddof))
    return X_std


def cov(Xi: list, Xj: list, ddof: int = 1) -> float:
    """【函数】计算协方差（默认计算修正值）"""
    s = 0
    n = len(Xi)
    for (x_in, x_jm) in zip(Xi, Xj):
        s = s + (x_in - ave(Xi)) * (x_jm - ave(Xj))
        # n += 1  # 如果不调用len()可以这样计数
    cov = s / (n-ddof)
    return cov


def cor(Xi: list, Xj: list) -> float:
    """【函数】相关系数（相关系数不受修正与否的影响）"""
    cor = cov(Xi, Xj) / (std(Xi) * std(Xj))
    return cor


def __matrix_compute(function_name, matrix: list) -> list:
    """【函数】矩阵元素之间的运算（高阶函数）"""    
    n = len(matrix)
    result_matrix = list( [] for vector in range(n) )
    i = 0
    j = 0
    while (i < n):
        while (j < n):
            result_matrix[i].append(function_name(matrix[i], matrix[j]))
            j += 1
        i += 1
        j = 0
    return result_matrix


def cov_mat(matrix: list) -> list:
    """【函数】协方差矩阵"""   
    mat_cov = __matrix_compute(cov, matrix)
    return mat_cov


def cor_mat(matrix: list) -> list:
    """【函数】相关系数矩阵"""   
    mat_cor = __matrix_compute(cor, matrix)
    return mat_cor


def __matrix_element(function_name, matrix: list) -> list:
    """【函数】矩阵每个元素进行相同的运算（高阶函数）"""    
    n = len(matrix)
    i = 0
    j = 0
    result_matrix = list( [] for vector in range(n) )
    while (i < n):
        while (j < n):
            result_matrix[i].append(function_name(matrix[i][j]))
            j += 1
        i += 1
        j = 0
    return result_matrix


def sin_mat(matrix: list) -> list:
    """【函数】"""
    mat_sin = __matrix_element(math.sin, matrix)
    return mat_sin


# 【方差分析相关功能的函数】将来进行“解耦”，放入“statistics.py”文件中
def Q(X):
    """
    【函数】

    功能：单因素方差分析中的Q

    参数：
    + X：[list 列表] 包含样本数据的Python二维列表

    返回值：
    + [float 浮点型] Q的值
    """
    i = 0         # 行下标（变量）
    r = len(X)    # 获取二维列表X的行数，也即方差分析中的r（对于一个确定问题为常量）
    j = 0         # 列下标（变量），由于调用的sum(X)函数内已经有一个计数功能，所以此变量没有用到
    n_i = 0
    S = 0
    Q = 0
    while(i < r):
        n_i = len(X[i])  # 获取二维列表第i行的列数，也即方差分析中的n_i
        S = ((sum(X[i]))**2)/n_i
        Q = Q + S
        i = i + 1
    return Q


def P(X):
    """
    【函数】

    功能：单因素方差分析中的P

    参数：
    + X：[list 列表] 包含样本数据的Python二维列表

    返回值：
    + [float 浮点型] P的值
    """
    i = 0         # 行下标（变量）
    r = len(X)    # 获取二维列表X的行数，也即方差分析中的r（对于一个确定问题为常量）
    j = 0         # 列下标（变量），由于调用的sum(X)函数内已经有一个计数功能，所以此变量没有用到
    n = 0         # 总的数据个数（即二维数组元素的总个数）
    n_i = 0
    S = 0
    P = 0
    while(i < r):
        n_i = len(X[i])  # 获取二维列表第i行的列数，也即方差分析中的n_i
        n = n + n_i
        S_i = sum(X[i])
        S = S + S_i
        i = i + 1
    P = (S**2)/n
    return P


def R(X):
    """
    【函数】

    功能：单因素方差分析中的P

    参数：
    + X：[list 列表] 包含样本数据的Python二维列表

    返回值：
    + [float 浮点型] R的值
    """
    i = 0         # 行下标（变量）
    r = len(X)    # 获取二维列表X的行数，也即方差分析中的r（对于一个确定问题为常量）
    j = 0         # 列下标（变量），由于调用的sum(X)函数内已经有一个计数功能，所以此变量没有用到
    n_i = 0       # 获取二维列表某行的列数
    n = 0         # 总的数据个数（即二维数组元素的总个数）
    S = 0
    R = 0
    while(i < r):
        n_i = len(X[i])  # 获取二维列表第i行的列数，也即方差分析中的n_i
        j = 0       # 这里一定要记得重置列下标（C语言中for函数第一句就是重置下标）
        while(j < n_i):
            S = (X[i][j])**2
            R = R + S
            j = j + 1
        i = i + 1
    return R


def sfav(X, alpha):
    """
    【函数】

    功能：单因素方差分析（Single Factor Analysis of Variance）

    参数：
    + X：[list 列表] 包含样本数据的Python二维列表
    + alpha：[float 浮点型] 方差分析的置信度（α）

    返回值：
    + [int 整型] 返回0表示函数正常运行 
    """
    # 离差平方和的计算
    Q_A = Q(X) - P(X)
    Q_E = R(X) - Q(X)
    Q_T = R(X) - P(X)
    # 自由度的计算
    r = 0
    n = 0
    F_A = 0
    F_E = 0
    F_T = 0
    i = 0
    j = 0
    r = len(X)
    while(i < r):
        n = n + len(X[i])
        i = i + 1
    F_A = r - 1
    F_E = n - r
    F_T = n - 1
    # 平均离差平方和的计算
    ave_Q_A = Q_A/F_A
    ave_Q_E = Q_E/F_E
    # F值的计算
    F = ave_Q_A / ave_Q_E
    # 显著性检验
    N = 0
    F_1 = 6.70
    F_5 = 3.06
    if(alpha == 0.05):
        F_alpha = F_5
        if(F >= F_alpha):
            N = 1
    elif(alpha == 0.01):
        F_alpha = F_1
        if(F >= F_alpha):
            N = 2
    else:
        print("【错误】当前不支持该置信度下的检验，请检查置信度参数是否正确输入！\n")
    # 输出方差分析表
    L = 100
    print("="*L)
    print("方差来源 \t离差平方和 \t自由度 \t平均离差平方和 \tF值 \t显著性", "")
    print("-"*L)    # format()用于控制小数位数
    print("组    间 \tQ_A =", format(Q_A, ".2f"), "\t", F_A, "\tave_A =",
          format(ave_Q_A, ".2f"), "\t", format(F, ".3f"), "\t", "*"*N)
    print("组    内 \tQ_E =", format(Q_E, ".2f"), "\t",
          F_E, "\tave_E =", format(ave_Q_E, ".2f"))
    print("-"*L)
    print("总    和 \tQ_T =", format(Q_T, ".2f"), "\t", F_T, "\t", "N.A.", "\t")
    print("="*L)
    return 0


def mfav(X):
    """
    【函数】

    功能：多因素方差分析（Multiply Factor Analysis of Variance）

    参数：
    + X：[list 列表] PASS

    返回值：
    + [float 浮点型] PASS
    """
    pass


# 【模块内测试代码】
if __name__ == "__main__":
    import numpy
    Sample = [18, 19, 18, 17, 20, 21, 23, 19, 16]
    x_i = [18, 19, 18, 17, 20, 21, 23, 19, 16]
    y_i = [4, 2, 7, 4, 1, 2, 6, 9, 5]
    matrix = [x_i, y_i]
    print("求和为：", sum(Sample))
    print("平均值为：", ave(Sample))
    print("方差为：", var(Sample, ddof=0))
    print("修正方差为：", var(Sample))
    print("标准差为：", std(Sample, ddof=0))
    print("协方差为（修正）：", cov(x_i, y_i))
    print("NumPy计算协方差阵:\n", numpy.cov(x_i, y_i))
    print("协方差矩阵:\n", cov_mat(matrix))
    print("相关系数为（修正）：", cor(x_i, y_i))
    print("NumPy计算相关系数阵:\n", numpy.corrcoef(x_i, y_i))
    print("相关系数矩阵:\n", cor_mat(matrix))
    print("正弦:\n", sin_mat(matrix))

else:
    print("【dapas.statistics加载成功】")
